package net.wicp.tams.common.connector.beans.property;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.Result;
import net.wicp.tams.common.connector.constant.ColProperty;
import net.wicp.tams.common.exception.ExceptAll;

@SuppressWarnings("rawtypes")
@Slf4j
public class JavaBeanHandler extends BasicNoHandler {
	private static final long serialVersionUID = 1L;
	private final static Logger logger = LoggerFactory.getLogger(JavaBeanHandler.class);
	private Class beanClass;//

	public JavaBeanHandler(String name, Class type, Class contentType) {
		super(name, type, contentType);
		this.beanClass = contentType;
	}

	public JavaBeanHandler(String name, Class type) {
		super(name, type);
		this.beanClass = type;
	}

	@Override
	protected Result checkSingleValue(Object value) {
		if (value == null || (this.beanClass!=null && value.getClass().isAssignableFrom(this.beanClass))) {
			return Result.getSuc();
		} else {
			if(this.beanClass==null) {
				logger.error("[{}]的类型不匹配，值[{}]没有找到对应的类型", name, value);
				return new Result(ExceptAll.Param_typenofit);
			}else {
				logger.error("[{}]的类型不匹配，应该是[{}],但传进来的参数是[{}]基本类型", name, beanClass.getName(), value.getClass().getName());
				return new Result(ExceptAll.Param_typenofit);
			}
		}
	}

	@Override
	public Object getSingleDefaultColValue() {
		String defaultValue = getAttriValue(ColProperty.defaultValue);
		if (StringUtils.isNotBlank(defaultValue)) {
			JSONObject json = JSONObject.parseObject(defaultValue);
			Object retdefaultobj = jsonTosingleObj(json);
			return retdefaultobj;
		} else {
			return null;
		}
	}

	@Override
	protected Object singleObjToJson(Object json) {
		String jsonstr = JSONObject.toJSONString(json);// java对象到json字
		return JSONObject.parse(jsonstr);
	}

	@Override
	protected Object jsonTosingleObj(Object obj) {
		// JSONObject inputobj = new JSONObject(String.valueOf(obj));
		JSONObject inputobj = (JSONObject) obj;
		@SuppressWarnings("unchecked")
		Object retobj = inputobj.toJavaObject(beanClass);
		return retobj;
	}

	private void setMock(Object bean,String filedName,Class type) {
		Object param = null;
		if (type == String.class)
			param = "abc";
		else if (type == int.class || type == Integer.class)
			param = 1;
		else if (type == long.class || type == Long.class)
			param = 1l;
		else if (type == byte.class || type == Byte.class)
			param = Byte.parseByte("1");
		else if (type == char.class || type == Character.class)
			param = "1".charAt(0);
		else if (type == float.class || type == Float.class)
			param = Float.parseFloat("1");
		else if (type == double.class || type == Double.class)
			param = Double.parseDouble("1.0");
		else if (type == short.class || type == Short.class)
			param = Short.parseShort("1");
		else if (type == boolean.class || type == Boolean.class)
			param = true;
		else if (Date.class.isAssignableFrom(type))
			param = new Date();
		else if (Enum.class.isAssignableFrom(type)) {
			try {
				Object[] enumConstants = type.getEnumConstants();
				if (ArrayUtils.isNotEmpty(enumConstants)) {
					param = enumConstants[0];
				} 
			} catch (Exception e) {
			}
		} else if (type == BigDecimal.class) {
			try {
				param = new BigDecimal("1.0");
			} catch (Exception e) {
			}
		} 
		try {
			BeanUtils.setProperty(bean, filedName, param);
		} catch (IllegalAccessException | InvocationTargetException e) {
			
		}
	}

	@Override
	protected Object mockObj() {
		Field[] fs = beanClass.getDeclaredFields(); // 得到所有的fields
		Object bean = null;
		try {
			bean = beanClass.newInstance();
		} catch (Exception e1) {
			log.error("需要无参的构造函数:", e1);
		}
		for (Field f : fs) {
			try {
				Class fieldClazz = f.getType(); // 得到field的class及类型全路径
				if (fieldClazz.isPrimitive())
					setMock(bean,f.getName(), fieldClazz);
				if (fieldClazz.getName().startsWith("java.lang"))
					setMock(bean,f.getName(), fieldClazz); // getName()返回field的类型全路径；
				if (fieldClazz.isAssignableFrom(List.class)) // 【2】
				{
					Type fc = f.getGenericType(); // 关键的地方，如果是List类型，得到其Generic的类型
					if (fc == null)
						continue;
					if (fc instanceof ParameterizedType) // 【3】如果是泛型参数的类型
					{
						ParameterizedType pt = (ParameterizedType) fc;
						Class genericClazz = (Class) pt.getActualTypeArguments()[0]; // 【4】
																						// 得到泛型里的class类型对象。
						// TODO genericClazz迭代
						Object obj = genericClazz.newInstance();
						BeanUtils.setProperty(bean, f.getName(), obj);
					}
				} else if (fieldClazz.isAssignableFrom(Map.class)) {
					Type fc = f.getGenericType();
					if (fc == null)
						continue;
					if (fc instanceof ParameterizedType) {
						ParameterizedType pt = (ParameterizedType) fc;
						Class param0 = (Class) pt.getActualTypeArguments()[0]; // 【4】
						Class param1 = (Class) pt.getActualTypeArguments()[1]; // 【4】
						Map values = new HashMap<>();
						// TODO param0,param1迭代
						Object obj = param0.newInstance();
						Object obj2 = param1.newInstance();
						values.put(obj, obj2);
						BeanUtils.setProperty(bean, f.getName(), values);
					}
				} else if (fieldClazz.isArray()) {
					Object obj = fieldClazz.getComponentType().newInstance();
					// TODO fieldClazz.getComponentType()迭代
					BeanUtils.setProperty(bean, f.getName(), new Object[] { obj });
				}
			} catch (Exception e) {
				log.error("setmockdata error:", e);
			}

		}
		return bean;
	}

}
